﻿using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Filters;
using System.Reflection;
using System.Security.Claims;
using WebCoreAPI.Identity;
using WebCoreAPI.Models;

namespace WebCoreAPI.Filter
{
    [AttributeUsage(AttributeTargets.Method)]
    public class UnCheckJWAttribute : Attribute { };


    /// <summary>
    /// JWT检测Version, 当数据库中的版本大于客户端时禁止访问
    /// </summary>
    public class JWTCheckFilter : IAsyncActionFilter
    {
        private readonly UserManager<MyUser> userManager;

        public JWTCheckFilter(UserManager<MyUser> userManager)
        {
            this.userManager = userManager;
        }
        public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
        {
            ControllerActionDescriptor? descriptor = context.ActionDescriptor as ControllerActionDescriptor;
            var attribute = descriptor.MethodInfo.GetCustomAttribute<UnCheckJWAttribute>();
            if (null != attribute)
            {
                await next();
                return;
            }
            long jwkVerson = Convert.ToInt64(context.HttpContext.User.FindFirstValue(ClaimTypes.Version) ?? "0");
            if (jwkVerson == 0)
            {
                context.Result = new ObjectResult("未获取到用户信息的jwkVersion") { StatusCode = 400 };
                return;
            }
            string id = context.HttpContext.User.FindFirstValue(ClaimTypes.NameIdentifier);
            if (string.IsNullOrEmpty(id))
            {
                context.Result = new ObjectResult("未获取到用户信息的Id") { StatusCode = 400 };
                return;
            }
            var user = await userManager.FindByIdAsync(id);
            if (user.JWTVersioin > jwkVerson)  //后台的版本大于JWK中的版本
            {
                context.Result = new ObjectResult("客户端的JWK过时") { StatusCode = 400 };
                return;
            }
            await next();


        }
    }
}
